fn main() {
    let ip1 = IpType::IPV4;
    println!("ip1 is {:?}", ip1);


    let ip1 = IPAddress {
        ip_type: IpType::IPV4,
        address: "127.0.0.1".to_string(),
    };
    println!("ip1 is {:?}", ip1);

    let ipv4 = IpAddr::IPV4(127, 0, 0, 1);
    let ipv6 = IpAddr::IPV6("32123123,25345345,34546,4564564".to_string());
    println!("ipv4 is {:?},   ipv6 is {:?}", ipv4, ipv6);
}


//枚举的定义
#[derive(Debug)]
enum IpType {
    IPV4,
    IPV6,
}


// 在结构体中使用枚举
#[derive(Debug)]
struct IPAddress {
    ip_type: IpType,
    address: String,
}

// 将数据附加到枚举上面,   不需要创建额外的struct
#[derive(Debug)]
enum IpAddr {
    IPV4(u8, u8, u8, u8),
    IPV6(String),
}


// 枚举关联的数据可以是任意类型， 可以是struct ， 或者是其他枚举
#[derive(Debug)]
enum Message {
    Quit,
    Move { x: i32, y: i32 }, // 匿名的struct
    Write(String),
    ChangeColor(i32, i32, i32),
}


//枚举定义方法
impl Message {
    fn call(&self) {
        println!("当前枚举是 {:?}", self)
    }
}


#[test]
fn test_enum_fn() {
    let quit = Message::Quit;

    let mov = Message::Move { x: 11, y: 22 };

    let w = Message::Write("wwww".to_string());

    let change = Message::ChangeColor(1, 2, 3);

    quit.call();
    mov.call();
    w.call();
    change.call();
}


//  Option 枚举

#[test]
fn test_option() {
    let p1 = Some("qqq");
    let p2 = Some(222);
    let p3: Option<String> = None;  //  必须指定类型，否则报错 ( type must be known at this point)


    println!(" p1 is {:?},   p2 is  {:?}   , p3 is {:?}", p1, p2, p3);

    //Option<T>  和T 是不同的类型

    let x = 22;

    let y: Option<i32> = Some(3);

    let sum = x + y.unwrap(); //  unwrap 是获取枚举里面的值

    println!("sum is {}", sum);
}


// match 匹配模式

enum Color {
    Red,
    Black,
    Bule,
    Green,
    Yellow,
}

// 枚举的模式匹配    类似switch  , match 必须匹配所有的模式
#[test]
fn test_enum_match() {
    let color = Color::Yellow;
    match color {
        Color::Red => println!("红色"),
        Color::Black => println!("黑色"),
        Color::Bule => println!("蓝色"),
        Color::Green => println!("绿色"),
        _ => println!("其他颜色"),   // _ 匹配剩下的
    }
}


// 绑定值的模式匹配
enum Response {
    Ok,
    Error { code: i32, message: String },
}

#[test]
fn test_response() {
    let resp = Response::Error { code: 500, message: "服务器异常".to_string() };
    match resp {
        Response::Ok => println!("success!!!!"),
        Response::Error { code, message } => {
            println!("code is {} , message is {}", code, message);
        }
    }
}


//  Option<T> 的匹配
fn plus_one(x: Option<i32>) -> Option<i32> {
    match x {
        None => None,
        Some(i) => Some(i + 1),
    }
}


#[test]
fn test_plus_one() {
    let p1 = Option::Some(1);

    println!("p1 is {:?}", p1);
    let p2 = plus_one(p1);


    println!("p2 is {:?}", p2);


    let none = None;
    let p3 = plus_one(none);

    println!("p3 is {:?}", p3);
}


